package router

import (
	"context"
	"fmt"
	"github.com/cloudwego/hertz/pkg/app"
	"github.com/cloudwego/hertz/pkg/app/client"
	"github.com/cloudwego/hertz/pkg/app/middlewares/client/sd"
	"github.com/cloudwego/hertz/pkg/app/server"
	"github.com/cloudwego/hertz/pkg/app/server/registry"
	"github.com/cloudwego/hertz/pkg/common/config"
	"github.com/cloudwego/hertz/pkg/common/utils"
	"github.com/cloudwego/hertz/pkg/protocol"
	"github.com/cloudwego/hertz/pkg/route"
	"github.com/go-mogu/mogu-gateway/global"
	"github.com/go-mogu/mogu-gateway/middleware"
	"github.com/go-mogu/mogu-gateway/pkg/consts"
	"github.com/go-mogu/mogu-gateway/pkg/response"
	"github.com/go-mogu/mogu-gateway/pkg/util"
	"github.com/go-mogu/mogu-gateway/router/routes"
	"github.com/go-mogu/mogu-registry/nacos"
	"github.com/hertz-contrib/reverseproxy"
	"github.com/nacos-group/nacos-sdk-go/v2/clients"
	"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client"
	"github.com/nacos-group/nacos-sdk-go/v2/vo"
	"strings"
)

func Register(address string) *server.Hertz {
	//获取本机ip
	addr := util.GetIpAddr()
	//nacos服务发现客户端
	nacosCli, err := clients.NewNamingClient(
		vo.NacosClientParam{
			ClientConfig:  &global.Cfg.Nacos.Client,
			ServerConfigs: global.Cfg.Nacos.Server,
		})
	if err != nil {
		panic(err)
	}
	addr = addr + ":" + address
	//注册服务
	r := nacos.NewNacosRegistry(nacosCli)
	h := server.Default(
		server.WithHostPorts("0.0.0.0"+":"+address),
		server.WithRegistry(r, &registry.Info{
			ServiceName: global.Cfg.App.Name,
			Addr:        utils.NewNetAddr("tcp", addr),
			Weight:      1,
			Tags:        global.Cfg.Nacos.Discovery.Metadata,
		}),
	)
	// [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
	// cors
	h.Use(middleware.ResponseHeader)
	h.Use(middleware.CorsAuth())
	// header add X-Request-Id
	// 404 not found
	h.NoRoute(func(c context.Context, ctx *app.RequestContext) {
		path := string(ctx.Request.URI().Path())
		method := string(ctx.Request.Method())
		response.NotFoundException(ctx, fmt.Sprintf("%s %s not found", method, path))
	})
	h.Static("/", "./public/")
	// 路由分组
	var (
		//publicMiddleware = []app.HandlerFunc{
		//	middleware.IpAuth(),
		//}
		//commonGroup  = h.Group("/", publicMiddleware...)
		commonGroup  = h.Group("/")
		swaggerGroup = h.Group("/")
	)
	//代理路由
	RegisterRoutes(nacosCli, h.Group(""))
	// 公用组
	routes.InitCommonGroup(commonGroup)
	// swagger
	routes.InitSwagger(swaggerGroup)
	// 赋给全局
	return h
}

func RegisterRoutes(cli naming_client.INamingClient, r *route.RouterGroup) {
	for _, routeItem := range global.Cfg.Routes {
		uriInfo, _ := util.ParseURL(routeItem.Uri, -1)
		serviceName := uriInfo["host"]
		if uriInfo["scheme"] == "lb" {
			r.Any("/"+serviceName+"/*any", ReverseProxy(serviceName, cli))
		}
	}

}

func ReverseProxy(serviceName string, cli naming_client.INamingClient) app.HandlerFunc {
	return func(c context.Context, ctx *app.RequestContext) {
		r := nacos.NewNacosResolver(cli)
		newClient, err := client.NewClient()
		if err != nil {
			panic(err)
		}
		newClient.Use(sd.Discovery(r))
		uri := ctx.Request.URI()
		path := fmt.Sprintf("%s:%s", string(uri.Scheme()), string(uri.Path()))
		query := string(uri.QueryString())
		if query != "" {
			path = path + "?" + query
		}
		proxy := &reverseproxy.ReverseProxy{Target: path}
		proxy.SetDirector(func(req *protocol.Request) {
			pathList := strings.Split(path, consts.PathSeparator)
			path = consts.PathSeparator + strings.Join(pathList[2:], consts.PathSeparator)
			req.SetRequestURI(path)
			req.SetOptions(config.WithSD(true))
			req.SetHost(serviceName)
		})
		proxy.SetClient(newClient)
		if err != nil {
			panic(err)
		}
		proxy.ServeHTTP(c, ctx)
	}
}
